﻿using Monti.MVVM;
using Newtonsoft.Json.Linq;

namespace WikiUploader.Classes.MediaWikiAccess
{
   /// <summary>
   /// Represents a page in a mediawiki wiki.
   /// </summary>
   public class MediaWikiPage : ViewModelBase
   {
      #region Fields

      private bool m_IsLoaded;

      private string m_LastTimestamp;
      private string m_LastComment;
      private string m_LastUser;
      private string m_Content;
      private string m_PageId;
      private string m_Title;

      #endregion

      #region Setup

      /// <summary>
      /// Creates a new media wiki page. This is done only from within a site object.
      /// </summary>
      /// <param name="site">Parent media wiki site.</param>
      /// <param name="pageTitle">Title of page.</param>
      internal MediaWikiPage (MediaWikiSite site, string pageTitle)
      {
         this.Site = site;
         this.Title = pageTitle;
         this.PageId = "Page does not exist.";
      }

      #endregion

      #region Properties

      /// <summary>
      /// Gets the site the page belongs to.
      /// </summary>
      public MediaWikiSite Site { get; private set; }

      /// <summary>
      /// Gets the name of the page.
      /// </summary>
      public string Title
      {
         get { return this.m_Title; }
         private set
         {
            this.m_Title = value;
            this.RaisePropertyChanged ("Title");
         }
      }

      /// <summary>
      /// Gets the page id.
      /// </summary>
      public string PageId
      {
         get { return this.m_PageId; }
         private set
         {
            this.m_PageId = value;
            this.RaisePropertyChanged ("PageId");
         }
      }

      /// <summary>
      /// Gets or Sets the content of the page.
      /// </summary>
      public string Content
      {
         get { return this.m_Content; }
         set
         {
            this.m_Content = value;
            this.RaisePropertyChanged ("Content");
         }
      }

      /// <summary>
      /// Gets or Sets the comment on the last edit.
      /// </summary>
      public string LastComment
      {
         get { return this.m_LastComment; }
         private set
         {
            this.m_LastComment = value;
            this.RaisePropertyChanged ("LastComment");
         }
      }

      /// <summary>
      /// Gets or Sets the user on the last edit.
      /// </summary>
      public string LastUser
      {
         get { return this.m_LastUser; }
         private set
         {
            this.m_LastUser = value;
            this.RaisePropertyChanged ("LastUser");
         }
      }

      /// <summary>
      /// Gets or Sets the timestamp of the last edit.
      /// </summary>
      public string LastTimestamp
      {
         get { return this.m_LastTimestamp; }
         private set
         {
            this.m_LastTimestamp = value;
            this.RaisePropertyChanged ("LastTimestamp");
         }
      }

      /// <summary>
      /// Gets or Sets if the page is loaded.
      /// </summary>
      public bool IsLoaded
      {
         get { return this.m_IsLoaded; }
         private set
         {
            this.m_IsLoaded = value;
            this.RaisePropertyChanged ("IsLoaded");
         }
      }

      /// <summary>
      /// Gets or Sets the url of the page.
      /// </summary>
      public string Url { get; private set; }

      #endregion

      #region Methods

      /// <summary>
      /// Delegate method called after a page is loaded.
      /// </summary>
      /// <param name="pageData">Page data.</param>
      internal void OnPageLoaded (JObject pageData)
      {
         var page = pageData ["query"] ["pages"].First.First;
         if (page["missing"] != null) return;
         this.PageId = page["pageid"].Value <string> ();
         this.Title = page["title"].Value <string> ();

         var revision = page["revisions"].First;
         this.LastComment = revision["comment"].Value <string> ();
         this.LastTimestamp = revision["timestamp"].Value<string> ();
         this.LastUser = revision["user"].Value<string> ();
         this.Content = revision["*"].Value<string> ();

         this.Url = this.Site.SiteInfo ["server"] + 
            this.Site.SiteInfo ["articlepath"].Value<string> ().Replace ("$1", this.Title.Replace (' ', '_'));
         this.Site.Out.WriteLine ("'{0}' loaded successfully.", this.Title);
         this.IsLoaded = true;
      }

      /// <summary>
      /// Updates the last edit time and user.
      /// </summary>
      /// <param name="newTimeStamp">Last edit time.</param>
      /// <param name="userName">Last edit user.</param>
      internal void UpdateTimeAndUser (string newTimeStamp, string userName)
      {
         this.LastTimestamp = newTimeStamp;
         this.LastUser = userName;
      }

      /// <summary>
      /// Refresh this page.
      /// </summary>
      public void Refresh ()
      {
         this.Site.RefreshPage (this);
      }

      /// <summary>
      /// Saves this page to the wiki.
      /// </summary>
      public void Save ()
      {
         this.Site.SavePage (this);
      }

      #endregion
   }
}
